Skip to main content

Custom attributes

Since most primitives of Graphics are Javascript functions, one can extend the set of their properties / attributes modifiers (aka RGBColor, Opacity and etc) by writing a WLJS Functions.

Group modifier

The easiest example will be making something similar to Translate, which creates an SVG group and evaluates all children within a new group. By accessing env object we can interact with a canvas and properties of the children.

Animated Rainbow stroke

Let's define our function using Javascript cells

.js

core.RainboxStroke = async (args, env) => {
const group = env.svg.append("g");
env.local.group = group;

let hue = 0;
let frame = 0;

function animateColor() {
if (frame % 2 === 0) {
hue = (hue + 4) % 360;
group.style('color', `hsl(${hue}, 100%, 50%)`);
}
frame++;
env.local.uid = requestAnimationFrame(animateColor);
}

animateColor();

//apply special SVG attribute value
//that all nested elements can inherit color of the group
await interpretate(args[0], {...env, svg: group, color:'currentColor', stroke:'currentColor'});

return group;
}

core.RainboxStroke.destroy = (args, env) => {
cancelAnimationFrame(env.local.uid);
env.local.group.remove();
}

core.RainboxStroke.virtual = true

core.RainboxStroke = async (args, env) => {
    const group = env.svg.append("g");
    env.local.group = group;

    let hue = 0;
    let frame = 0;

    function animateColor() {
      if (frame % 2 === 0) {
        hue = (hue + 4) % 360;
        group.style('color', `hsl(${hue}, 100%, 50%)`);
      }
      frame++;
      env.local.uid = requestAnimationFrame(animateColor);
    }

    animateColor();

	//apply special SVG attribute value
	//that all nested elements can inherit color of the group
    await interpretate(args[0], {...env, svg: group, color:'currentColor', stroke:'currentColor'});
  
    return group;  
}

core.RainboxStroke.destroy = (args, env) => {
  cancelAnimationFrame(env.local.uid);
  env.local.group.remove();
}

core.RainboxStroke.virtual = true

Here we can apply it directly to Line, Text, Disk or any other primitives or group of primitives which use stroke or fill color

Graphics[{
RegularPolygon[4],
RainboxStroke[{
RegularPolygon[3],
Translate[Rotate[Text[Style["Hello World", FontSize->20], {0,0}], 45Degree],{0.4,0.4}]
}]
}]

The result:

(*VB[*)(Graphics[{RegularPolygon[4], RainboxStroke[{RegularPolygon[3], Translate[Rotate[Text[Style["Hello World", FontSize -> 20], {0, 0}], 45*Degree], {0.4, 0.4}]}]}])(*,*)(*"1:eJyNT0sOwiAUrN9ojK48gB7AM7gx6sKFKU1cU32tLyLPAE1ab6I38zZCsZi4ksXAZOYNb+YpxVkriiLdtbAlcfJsYGGj+O2MR521G32H2nh9YiGGvBBc7UlUOUl0Bi+OnchRplQyo+gCfyZ0XEJtHVpIFJdacPOZ7js/mcBdWgKl8axngZlKABu5HiAEzQ6kbJ1gjgsBda81ScPwDjgN/zWrob2jGr6xCV5B46LZYQW5gp9G6vlw57UMjzfTIU+7"*)(*]VB*)